#ifndef BUS_BA_H
#define BUS_BA_H
/*
  author Sylvain Bertrand <sylvain.bertrand@gmail.com>
  Protected by linux GNU GPLv2
  Copyright 2012-2014
*/
#define BA_ERR 901

#define BA_MAP_COHERENT_CONTIG	1
#define BA_MAP_KERNEL_SG	2
#define BA_MAP_USER_SG		3

/* how the write back page is split */
#define WB_SCRATCH_OF		0
#define WB_GPU_3D_RPTR_OF	1024
#define WB_GPU_C_0_RPTR_OF	1280
#define WB_GPU_C_1_RPTR_OF	1536
#define WB_DMA_0_RPTR_OF	1792
#define WB_IH_WPTR_OF		2048 /* ih is gpu driven, then wptr, not rptr */
#define WB_DMA_1_RPTR_OF	2304
#define WB_DMA_0_FENCE_OF	3072
#define WB_DMA_1_FENCE_OF	3076

struct ba_map {
	struct list_head n;
	u8 type;

	u64 ptes_start;		/* location of the pte table in (v)ram */
	u64 ptes_n;

	void __iomem *cpu_addr;
	u64 gpu_addr;

	dma_addr_t bus_addr; /* only for BA_MAP_COHERENT_CONTIG */

	/* only for BA_MAP_KERNEL_SG */
	struct page **cpu_ps;
	u64 cpu_ps_n;
	struct sg_table sg_tbl;
	int sg_tbl_list_nents;
};

struct ba {
	dma_addr_t dummy_bus_addr;
	void *dummy_cpu_addr;

	struct ba_map *wb_map;
	struct ba_map *ih_ring_map;
	struct ba_map *gpu_3d_ring_map;
	/*
	 * XXX: compute rings are exactly the same, should array them like the
	 * dma rings
	 */
	struct ba_map *gpu_c0_ring_map;
	struct ba_map *gpu_c1_ring_map;
	struct ba_map *dma_rings_maps[DMAS_N];
	struct ba_map *pt_map;

	u64 pt_start;		/* location of the page table in (v)ram */
	u64 ptes_n;

	/* from here we are protected by the sem */
	struct rw_semaphore maps_sem;
	struct rng mng;		/* range manager of the aperture */
	struct list_head maps;
};

/* major bus aperture functions */
long ba_dummy_page_alloc(struct pci_dev *dev);
long ba_init_once(struct pci_dev *dev);
long ba_init(struct pci_dev *dev);
long ba_core_map(struct pci_dev *dev);
long ba_map(struct pci_dev *dev, void __iomem *cpu_addr,
					struct sg_table *sg_tbl, int nents);
void ba_unmap(struct pci_dev *dev, void __iomem *cpu_addr);
#define BA_NO_PT_UPDATE		BIT(0)
void ba_all_unmap(struct pci_dev *dev, u8 flgs);
void ba_shutdown(struct pci_dev *dev);
#endif
